﻿
using System.Linq.Expressions;

using EvaluationSystem.Dto;
using EvaluationSystem.Models;
using EvaluationSystem.ViewModels;

using Microsoft.EntityFrameworkCore;

namespace EvaluationSystem.Utils;

public static class PageUtil
{
    /// <summary>
    /// 分页帮助方法, 通过泛型和数据自动分页
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="pageDto"></param>
    /// <param name="people"></param>
    /// <param name="pendExpression"></param>
    /// <returns></returns>
    public static PageDataVM<List<T>> GetAutoPageList<T>(this PageDto pageDto, People people,
        Expression<Func<IQueryable<T>>> pendExpression) where T : class, new()
    {
        var pendListExpress = pendExpression;
        var list = GetPageList(pageDto, pendListExpress.Compile().Invoke(), out var pageInfoVm);
        var pageData = new PageDataVM<List<T>>()
        {
            People = people,
            PageInfoVM = pageInfoVm,
            Data = list,
        };
        return pageData;
    }

    /// <summary>
    /// 分页帮助方法
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="pageDto"></param>
    /// <param name="pendList"></param>
    /// <param name="pageInfoVm"></param>
    /// <returns></returns>
    public static List<T> GetPageList<T>(this PageDto pageDto, IQueryable<T> pendList, out PageInfoVM pageInfoVm) where T : class, new()
    {
        List<T> list;
        int skipSize = 0;
        int takeSize = pageDto.pageSize > 0 ? pageDto.pageSize : 6;
        int totalSize = pendList.Count();
        if (pageDto.pageAction != null)
        {
            skipSize = pageDto.InvokeFuncByPageAction(pageDto =>
            {
                if (pageDto.page < Math.Ceiling((float)totalSize/(float)pageDto.page))
                    pageDto.page++;
                return pageDto.pageSize * (pageDto.page-1);
            }, pageDto =>
            {
                if (pageDto.page > 1)
                    pageDto.page--;
                return pageDto.page > 1 ? pageDto.pageSize * (pageDto.page - 1) : 0;
            });
        }
        else
        {
            skipSize = pageDto.pageSize * (pageDto.page - 1);
        }
        list = pendList.Skip(skipSize).Take(takeSize).ToList();

        pageInfoVm = new PageInfoVM()
        {
            CurrentPage = pageDto.page,
            PageSize = pageDto.pageSize,
            TotalSize = totalSize,
        };
        return list;
    }

    public static int InvokeFuncByPageAction(this PageDto pageDto, Func<PageDto, int> nextFunc, Func<PageDto, int> previousFunc)
    {
        if (pageDto.pageAction != null)
        {
            int skipSize = pageDto.pageAction.Value switch
            {
                PageAction.Next => nextFunc(pageDto),
                PageAction.Previous => previousFunc(pageDto),
                _ => 0
            };
            return skipSize;
        }

        return 0;
    }
}